<?php
/**********************************************************************************
WIKINDX: Bibliographic Management system.
Copyright (C)

This program is free software; you can redistribute it and/or modify it under the terms 
of the GNU General Public License as published by the Free Software Foundation; either 
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; 
if not, write to the 
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

The WIKINDX Team 2007
sirfragalot@users.sourceforge.net
**********************************************************************************/
/*****
*	ADMINUSER class.
*
*	Administration of users
*****/
class ADMINUSER
{
// Constructor
	function ADMINUSER($db, $vars)
	{
		$this->db = $db;
		$this->vars = $vars;
		include_once("core/session/SESSION.php");
		$this->session = new SESSION();
		include_once("core/template/TEMPLATE.php");
		$this->template = new TEMPLATE('content');
		include_once("core/messages/MESSAGES.php");
		$this->messages = new MESSAGES();
		include_once("core/messages/SUCCESS.php");
		$this->success = new SUCCESS();
		include_once("core/messages/ERRORS.php");
		$this->errors = new ERRORS();
		include_once("core/html/HTML.php");
		$this->html = new HTML();
		include_once("core/html/MISC.php");
		include_once("core/html/FORM.php");
		include_once("core/html/TABLE.php");
		include_once("core/user/USER.php");
		$this->user = new USER($this->db, $this->vars);
	}
// check we really are admin
	function gateKeep($method)
	{
		if(!$this->session->getVar("setup_superadmin"))
		{
			include_once("core/authorize/AUTHORIZE.php");
			$authorize = new AUTHORIZE($this->db);
			if($pString = $authorize->initLogon())
				return $pString;
		}
// else, run $method
		return $this->$method();
	}
// display options for users
	function display($message = FALSE)
	{
		$this->template->setVar("heading", $this->messages->text("heading", "user"));
		$pString = '';
		if($message)
			$pString .= MISC::p($message);
		$pString .= MISC::p(MISC::a("link", $this->messages->text("user", "addLabel"), 
			"index.php?action=adminUserAddInit"));
		$this->grabUsers();
		if(!empty($this->users))
		{
			$pString .= MISC::p(MISC::a("link", $this->messages->text("user", "deleteLabel"), 
				"index.php?action=adminUserDeleteInit"));
			$pString .= MISC::p(MISC::a("link", $this->messages->text("user", "editLabel"), 
				"index.php?action=adminUserEditInit"));
		}
// Pending registration requests
		$resultset = $this->db->select(array('WKX_user_register'), array('id', 'email', 'timestamp', 'request'), 
			' WHERE ' . $this->db->formatField('confirmed') . '=' . $this->db->tidyInput('N') . 
			' AND ' . $this->db->formatField('request') . 'IS NOT NULL');
		if($this->db->numRows($resultset))
		{
			$pString .= MISC::hr();
			$pString .= MISC::h($this->messages->text('user', 'pendingRegistration1'));
			$pString .= MISC::p($this->messages->text('user', 'pendingRegistration2')) . MISC::br();
			$pString .= FORM::formHeader("registerRequestManage");
			while($row = $this->db->fetchRow($resultset))
			{
				$pString .= TABLE::tableStart();
				$pString .= TABLE::trStart();
				$pString .= TABLE::trEnd();
				$pString .= TABLE::td($row['email']);
				$pString .= TABLE::td($this->html->dbToHtmlTidy($row['request']));
				$pString .= TABLE::td($row['timestamp']);
				$pString .= TABLE::td($this->messages->text('user', 'registrationAccept') . "&nbsp:&nbsp;" . 
					FORM::radioButton(FALSE, 'registerUser_' . $row['id'], 'accept', TRUE) .  
					MISC::br() . $this->messages->text('user', 'registrationDecline') . "&nbsp:&nbsp;" . 
					FORM::radioButton(FALSE, 'registerUser_' . $row['id'], 'decline'));
				$pString .= TABLE::tableEnd();
				$pString .= MISC::br() . "&nbsp;" . MISC::br();
			}
			$pString .= MISC::p(FORM::formSubmit("Proceed"), FALSE, "right");
			$pString .= FORM::formEnd();
		}
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Mangage requests for registration
	function registerRequestManage()
	{
		foreach($this->vars as $key => $value)
		{
			if(strpos($key, "registerUser_") !== FALSE)
			{
				$split = explode("_", $key);
				$registerIds[$split[1]] = $value;
			}
		}
		if(!isset($registerIds))
			return $this->badInput($this->errors->text("inputError", "missing"), 'display');
		$this->template->setVar("heading", $this->messages->text("heading", "user"));
		include_once("core/email/EMAIL.php");
		$emailClass = new EMAIL($this->db, $this->vars);
		if(!$emailClass->registerRequestManage($registerIds))
			$this->badInput($this->errors->text("inputError", "mail2"), 'display');
		return $this->display($this->success->text('registerRequestManage'));
	}
// Add a user - display options.
	function addInit($error = FALSE)
	{
		$this->template->setVar("heading", $this->messages->text("heading", "user", 
		" (" . $this->messages->text("user", "addLabel") . ")"));
		$pString = '';
		if($error)
			$pString .= MISC::p($error, "error", "center");
		$pString .= FORM::formHeader("adminUserAdd");
		$pString .= TABLE::tableStart();
		$pString .= TABLE::trStart();
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "username"), "username", FALSE, 20, 255)
			 . " " . MISC::span('*', 'required'));
		$pString .= TABLE::td(FORM::passwordInput($this->messages->text("user", "password"), "password", FALSE, 15, 255)
			 . " " . MISC::span('*', 'required'));
		$pString .= TABLE::td(FORM::passwordInput($this->messages->text("user", "passwordConfirm"), 
			"passwordConfirm", FALSE, 15, 255) . " " . MISC::span('*', 'required'));
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "email"), "email", FALSE, 30, 255)
			 . " " . MISC::span('*', 'required'));
		$pString .= TABLE::trEnd();
		$pString .= TABLE::tableEnd();
		$pString .= MISC::br() . "&nbsp;" . MISC::br();
		$pString .= TABLE::tableStart();
		$pString .= TABLE::trStart();
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "fullname"), "fullname", FALSE, 30, 255));
		$pString .= TABLE::td(FORM::checkbox($this->messages->text("user", "admin"), "admin", FALSE));
		$pString .= TABLE::trEnd();
		$pString .= TABLE::tableEnd();
		$pString .= MISC::p(FORM::formSubmit("Add"), FALSE, "right");
		$pString .= FORM::formEnd();
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Add a user
	function add()
	{
		if(!$this->validateInput('adminAdd'))
			$this->badInput($this->errors->text("inputError", "missing"), 'addInit');
// NB - writeUser returns FALSE on success!
		if($this->user->writeUser(TRUE, 2))
			$this->badInput($this->errors->text("inputError", "userExists"), "addInit");
		$pString = $this->success->text("user", " " . $this->messages->text("misc", "added") . " ");
		return $this->display($pString);
	}
// Delete users display.
	function deleteInit($error = FALSE)
	{
		$this->template->setVar("heading", $this->messages->text("heading", "user", 
		" (" . $this->messages->text("user", "deleteLabel") . ")"));
		$this->grabUsers();
		if(empty($this->users))
			$this->failure($this->messages->text("resources", "noUsers"));
		$pString = '';
		if($error)
			$pString .= MISC::p($error, "error", "center");
		$pString .= FORM::formHeader("adminUserDeleteConfirm");
		$pString .= FORM::selectFBoxValueMultiple(FALSE, "userDelete", $this->users, 20);
		$pString .= MISC::br() . $this->messages->text("hint", "multiples") . MISC::br();
		$pString .= MISC::br() . FORM::formSubmit('Delete');
		$pString .= FORM::formEnd();
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Ask for confirmation of delete users
	function deleteConfirm()
	{
		if(!$input = $this->validateInput('delete'))
			$this->badInput($this->errors->text("inputError", "invalid"), 'deleteInit');
		$this->template->setVar("heading", $this->messages->text("heading", "user", 
		" (" . $this->messages->text("user", "deleteLabel") . ")"));
		$this->grabUsers();
		$users = "'" . implode("', '", array_keys(array_intersect(array_flip($this->users), $this->vars['userDelete']))) . "'";
		$pString = MISC::p($this->messages->text("user", "deleteConfirm", ": $users"));
		$pString .= FORM::formHeader("adminUserDelete");
		foreach($this->vars['userDelete'] as $id)
			$pString .= FORM::hidden("userDelete_" . $id, $id);
		$pString .= MISC::br() . FORM::formSubmit('Confirm');
		$pString .= FORM::formEnd();
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Delete user(s)
	function delete()
	{
		if(!$input = $this->validateInput('deleteConfirm'))
			$this->badInput($this->errors->text("inputError", "invalid"), 'deleteInit');
// $input is an array of user IDs
		if(!$this->user->deleteSql($input))
			$this->badInput($this->errors->text("inputError", "invalid"), 'deleteInit');
		$pString = $this->success->text("user", " " . $this->messages->text("misc", "deleted") . " ");
		return $this->display($pString);
	}
// display users for editing
	function editInit($error = FALSE)
	{
		$this->template->setVar("heading", $this->messages->text("heading", "user", 
		" (" . $this->messages->text("user", "editLabel") . ")"));
		$pString = '';
		if($error)
			$pString .= MISC::p($error, "error", "center");
		$pString .= FORM::formHeader("adminUserEditDisplay");
		$this->grabUsers();
		$pString .= FORM::selectFBoxValue(FALSE, "editId", $this->users, 20) . MISC::br() . FORM::formSubmit('Edit');
		$pString .= FORM::formEnd();
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// display one user for editing
// We temporarily use the session array 'mywikindx_' for storage so we can use the USER class methods.
	function editDisplay($error = FALSE)
	{
		$this->userId = FALSE;
		if(array_key_exists("editId", $this->vars))
			$this->userId = trim($this->vars["editId"]);
		else if(array_key_exists("userId", $this->vars))
			$this->userId = trim($this->vars["userId"]);
		if(!$this->validateInput('editId'))
			$this->badInput($this->errors->text("inputError", "invalid"), 'editInit');
		$this->template->setVar("heading", $this->messages->text("heading", "user", 
		" (" . $this->messages->text("user", "editLabel") . ")"));
		$pString = '';
		if($error)
			$pString .= MISC::p($error, "error", "center");
		else
			$this->user->loadSession($this->userId);
		$pString .= $this->user->displayUserDetails("adminUserEdit", $this->userId);
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Edit user
	function edit()
	{
		if(!$this->validateInput('edit'))
			$this->badInput($this->errors->text("inputError", "invalid"), 'editDisplay');
		$this->template->setVar("heading", $this->messages->text("heading", "user", 
		" (" . $this->messages->text("user", "editLabel") . ")"));
// writeUser() returns FALSE for success
		if($this->user->writeUser(FALSE, 2))
			$this->failure($this->errors->text("inputError", "invalid"));
		$pString = $this->success->text("user", " " . $this->messages->text("misc", "edited") . " ");
		return $this->display($pString);
	}
// validate input
	function validateInput($type)
	{
		if($type == 'adminAdd')
		{
			if(!trim($this->vars['username']) || !trim($this->vars['password']) || 
				!trim($this->vars['passwordConfirm']) || !trim($this->vars['email']))
				return FALSE;
			if(trim($this->vars['password']) != trim($this->vars['passwordConfirm']))
				return FALSE;
		}
		else if($type == 'userAdd')
		{
			if(!trim($this->vars['username']) || !trim($this->vars['password']) || 
				!trim($this->vars['passwordConfirm']) || !$this->vars['email'] || !$this->vars['hashKey'])
				return FALSE;
			if(trim($this->vars['password']) != trim($this->vars['passwordConfirm']))
				return FALSE;
		}
		else if($type == 'register')
		{
			if(!trim($this->vars['email']))
				return FALSE;
		}
		else if($type == 'delete')
		{
			if(!array_key_exists('userDelete', $this->vars) || empty($this->vars['userDelete']))
				return FALSE;
		}
		else if($type == 'deleteConfirm')
		{
			$input = array();
// Ensure we don't delete superadmin with id of 1
			foreach($this->vars as $key => $value)
			{
				if(!$value || ($value == 1))
					continue;
				if(!preg_match("/userDelete_/", $key, $matches))
					continue;
				$input[] = $value;
			}
			 if(empty($input))
				return FALSE;
		}
		else if($type == 'editId')
		{
			if(!$this->userId)
				return FALSE;
		}
		else if($type == 'edit')
		{
			if(!trim($this->vars['password']) || !trim($this->vars['email']) || !trim($this->vars['userId']))
				return FALSE;
		}
		if(isset($input))
			return $input;
		return TRUE;
	}
// display options for user registration
	function initRegister($error = FALSE)
	{
		$this->template->setVar("heading", $this->messages->text("heading", "register"));
		$pString = '';
		if($error)
			$pString .= MISC::p($error, "error", "center");
		$recordset = $this->db->select(array('WKX_config'), 'registrationModerate');
		$registrationModerate = $this->db->fetchOne($recordset);
		if($registrationModerate == 'Y')
		{
			$pString .= MISC::p($this->messages->text('config', 'registrationRequest1'));
			$pString .= FORM::formHeader("registerRequest");
		}
		else
			$pString .= FORM::formHeader("registerUser");
		$pString .= TABLE::tableStart();
		$pString .= TABLE::trStart();
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "email"), "email", FALSE, 30, 255)
			 . " " . MISC::span('*', 'required') . 
			 ($registrationModerate == 'N' ? MISC::br() . $this->messages->text("hint", "registerEmail") : FALSE));
		$pString .= TABLE::trEnd();
		$pString .= TABLE::trStart();
		if($registrationModerate == 'Y')
			$pString .= TABLE::td(MISC::br() . FORM::textareaInput($this->messages->text("config", "registrationRequest2"),
				"registerRequest", FALSE, 75, 15));
		$pString .= TABLE::trEnd();
		$pString .= TABLE::tableEnd();
		$pString .= MISC::p(FORM::formSubmit("Proceed"), FALSE, "right");
		$pString .= FORM::formEnd();
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Write registration details and send confirmation email
	function register()
	{
// check we're not reloading
		if($this->session->getVar("register_lock"))
			$this->failure($this->errors->text("done", "register"));
		if(!$this->validateInput('register'))
			$this->badInput($this->errors->text("inputError", "missing"), 'initRegister');
// time() should be unique enough
		$hashKey = md5(time());
		include_once("core/email/EMAIL.php");
		$emailClass = new EMAIL(FALSE, $this->vars);
		if(!$email = $emailClass->register($hashKey))
			$this->badInput($this->errors->text("inputError", "mail"), 'initRegister');
// END email
// Now write details to WKX_user_register database
		$fields[] = 'hashKey';
		$values[] = $hashKey;
		$fields[] = 'email';
		$values[] = trim($this->html->removeNl($email));
		$fields[] = 'timestamp';
		$values[] = $this->db->formatTimestamp();
		$this->db->insert("WKX_user_register", $fields, $values);
// do some housekeeping by removing dead registrations older than 10 days
		$this->db->delete('WKX_user_register', "WHERE DATE_SUB(CURDATE(), INTERVAL 10 DAY) >= " . 
			$this->db->formatField('timestamp'));
		$this->db->optimize('WKX_user_register');
// Lock to prevent re-registration
		$this->session->setVar("register_lock", TRUE);
		$pString = $this->success->text("registerEmail");
		$this->template->setVar("heading", $this->messages->text("heading", "register"));
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// user has entered hashkey for confirmation
	function registerConfirm($error = FALSE)
	{
		if(!array_key_exists('hashKey', $this->vars))
			$this->failure($this->errors->text("inputError", "missing"));
// $this->vars['hashKey'] -> check it exists in WKX_user_register
		$recordset = $this->db->select(array('WKX_user_register'), array('id', 'email'), " WHERE " . 
			$this->db->formatField('hashKey') . " = " . $this->db->tidyInput($this->vars['hashKey']));
		if(!$this->db->numRows($recordset))
			$this->failure($this->errors->text("inputError", "noHashKey"));
		$row = $this->db->fetchRow($recordset);
		$id = $row['id'];
		$email = $row['email'];
		$this->template->setVar("heading", $this->messages->text("heading", "register"));
		$pString = '';
		if($error)
			$pString .= MISC::p($error, "error", "center");
		$pString .= FORM::formHeader("registerUserAdd");
		$pString .= FORM::hidden('id', $id);
		$pString .= FORM::hidden('hashKey', $this->vars['hashKey']);
		$pString .= FORM::hidden('email', $email);
		$pString .= TABLE::tableStart();
		$pString .= TABLE::trStart();
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "username"), "username", FALSE, 20, 255)
			 . " " . MISC::span('*', 'required'));
		$pString .= TABLE::td(FORM::passwordInput($this->messages->text("user", "password"), "password", FALSE, 15, 255)
			 . " " . MISC::span('*', 'required'));
		$pString .= TABLE::td(FORM::passwordInput($this->messages->text("user", "passwordConfirm"), 
			"passwordConfirm", FALSE, 15, 255) . " " . MISC::span('*', 'required'));
		$pString .= TABLE::td(FORM::textInput($this->messages->text("user", "fullname"), "fullname", FALSE, 30, 255));
		$pString .= TABLE::trEnd();
		$pString .= TABLE::tableEnd();
		$pString .= MISC::p(FORM::formSubmit("Add"), FALSE, "right");
		$pString .= FORM::formEnd();
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Add a user (self registration)
	function registerUserAdd()
	{
		if(!$this->validateInput('userAdd'))
			$this->badInput($this->errors->text("inputError", "missing"), "registerConfirm");
// NB - writeUser returns FALSE on success!
		if($this->user->writeUser(TRUE, 0))
			$this->badInput($this->errors->text("inputError", "userExists"), "registerConfirm");
// remove id from WKX_user_register
		$this->db->delete('WKX_user_register', "WHERE " . $this->db->formatField('id') . " = " . 
			$this->db->tidyInput($this->vars['id']));
		$this->db->optimize('WKX_user_register');
// grab id and write initial session details to grant write access
		$recordset = $this->db->select(array('WKX_users'), array('id'), 
			" WHERE " . 
			$this->db->formatField('username') . " = " . $this->db->tidyInput($this->vars['username']));
		$userId = $this->db->fetchOne($recordset);
		$this->session->setVar("setup_userId", $userId);
		$this->session->setVar("setup_write", TRUE);
// Write default preferences (TRUE == insert)
		$this->user->writePreferences($userId);
		include_once("core/email/EMAIL.php");
		$emailClass = new EMAIL($this->db, $this->vars);
		$emailClass->registerUserAdd();
		$this->template->setVar("heading", $this->messages->text("heading", "register"));
		$pString = $this->success->text("user", " " . $this->messages->text("misc", "added") . " ");
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// Store request for registration
	function registerRequest()
	{
// check we're not reloading
		if($this->session->getVar("register_lock"))
			$this->failure($this->errors->text("done", "register"));
		if(!$email = trim($this->vars['email']))
			$this->badInput($this->errors->text('inputError', 'missing'), 'initRegister');
		if(!$request = trim($this->vars['registerRequest']))
			$this->badInput($this->errors->text('inputError', 'missing'), 'initRegister');
		include_once("core/email/EMAIL.php");
		$emailClass = new EMAIL($this->db, $this->vars);
		if(!$emailClass->registerRequest($email))
			$this->badInput($this->errors->text("inputError", "mail"), 'initRegister');
// Now write details to WKX_user_register database
		$fields[] = 'hashKey';
		$values[] = md5(time());
		$fields[] = 'email';
		$values[] = trim($this->html->removeNl($email));
		$fields[] = 'request';
		$values[] = trim($this->html->removeNl($request));
		$fields[] = 'timestamp';
		$values[] = $this->db->formatTimestamp();
		$this->db->insert("WKX_user_register", $fields, $values);
// Lock to prevent re-registration
		$this->session->setVar("register_lock", TRUE);
		$pString = $this->success->text("registerRequest");
		$this->template->setVar("heading", $this->messages->text("heading", "register"));
		$this->template->setVar('body', $pString);
		return $this->template->process();
	}
// grab users from database
	function grabUsers()
	{
		$this->users = $this->user->grabAll(TRUE);
// don't allow this user to operate on self or superadmin (id == 1)
		$this->selfId = $this->session->getVar('setup_userId');
		if(array_key_exists($this->selfId, $this->users))
			unset($this->users[$this->selfId]);
		if(array_key_exists(1, $this->users))
			unset($this->users[1]);
	}
// bad Input function
	function badInput($error, $method)
	{
		include_once("core/html/CLOSE.php");
		new CLOSE($this->db, $this->$method($error));
	}
// failure - bomb out
	function failure($error)
	{
		$this->template->setVar("heading", $this->messages->text("heading", "register"));
		include_once("core/html/CLOSE.php");
		$this->template->setVar('body', $error);
		new CLOSE($this->db, $this->template->process());
	}
}
?>
